'''
Created on Jul 27, 2010

@author: Aidamina
'''
import os

from google.appengine.api import memcache
from google.appengine.ext import db

class Cache(object):
    '''
    classdocs
    '''    
    enabled = False
    version = os.environ.get('CURRENT_VERSION_ID','0')
    client = memcache.Client()
    
    @staticmethod
    def id(*items, **kwargs):
        result = []
        add = result.append
        for item in items:
            if isinstance(item, db.Model):
                add(str(item.key()))
            else:
                add(str(item))
        if len(result)==0:
            if isinstance(kwargs['value'], db.Model):
                add(str(kwargs['value'].key()))
            else:
                add(str(hash(kwargs['value'])))
        return '_'.join([]+result);
    
    @staticmethod
    def namespace(**kwargs):
        ns = [Cache.version]
        add = ns.append
        if kwargs.get('type',None):
            add(kwargs['type'].__name__)
            add(str(hash(kwargs['type'])))
        else:
            add(Cache.__name__)
            add(str(hash(Cache)))
        if kwargs.get('namespace', None):
            add(str(kwargs['namespace']))
        return '_'.join(ns)
        
    @staticmethod    
    def delete(*items, **kwargs):
        if not Cache.enabled:
            return False        
        return Cache.client.delete(Cache.id(*items, **kwargs), namespace=Cache.namespace(**kwargs))
    
    @staticmethod
    def set(*items, **kwargs):
        if not Cache.enabled:
            return False
        if not kwargs['value']:
            raise "No value"
        namespace = Cache.namespace(**kwargs)
        key = Cache.id(*items,**kwargs)
        if Cache.client.set(key, kwargs['value'], namespace = namespace):
            return key, namespace
        else:
            return False
        
    @staticmethod
    def get(*items, **kwargs):
        if not Cache.enabled:
            return None
        return Cache.client.get(Cache.id(*items), namespace = Cache.namespace(**kwargs))
        
class CachedModel(db.Model):
    use_cache = True    
    def put(self):
        ret = super(CachedModel, self).put()        
        if CachedModel.use_cache:
            Cache.set(value = self, type = self.__class__)
        return ret
            
    def delete(self):
        super(CachedModel, self).delete()
        Cache.delete(value = self, type = self.__class__)  
   
    @classmethod
    def get(cls,keys, **kwargs):
        if type(keys) is list:
            result =[]
            for key in keys:
                result.append(CachedModel.get(key, **kwargs))
            return result
        item = Cache.get(keys)
        if item:
            Cache.client.incr(str(cls.__name__)+'_cache', 1, 'CachedModel_stats', initial_value = 0)            
        else:
            item = super(CachedModel, cls).get(keys, **kwargs)
            if item:
                Cache.set(value = item, type = item.__class__)
                Cache.client.incr(str(cls.__name__) + '_datastore', 1, 'CachedModel_stats', initial_value = 0)            
        return item
        